﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using l1cs.server.templates;
using l1cs.server.serverpackets;
using System.Threading;

namespace l1cs.server.model.Instance
{
    public class L1DollInstance : L1NpcInstance
    {
        public const int DOLLTYPE_BUGBEAR = 0;
        public const int DOLLTYPE_SUCCUBUS = 1;
        public const int DOLLTYPE_WAREWOLF = 2;
        public const int DOLLTYPE_ELDER = 3;
        public const int DOLLTYPE_CRUSTANCEAN = 4;
        public const int DOLLTYPE_GOLEM = 5;
        public const int DOLL_TIME = 1800000;

        private static Logger _log = Logger.getLogger( typeof( L1DollInstance ).FullName );
        private Timer _dollFuture;
        private static Random _random = new Random();
        private int _dollType;
        private int _itemObjId;

        // ターゲットがいない場合の処理
        override public bool noTarget()
        {
            if ( _master.isDead() )
            {
                deleteDoll();
                return true;
            }
            else if ( _master != null && _master.getMapId() == getMapId() )
            {
                if ( getLocation().getTileLineDistance( _master.getLocation() ) > 2 )
                {
                    int dir = moveDirection( _master.getX(), _master.getY() );
                    if ( dir == -1 )
                    {
                        if ( !isAiRunning() )
                        {
                            startAI();
                        }
                        return true;
                    }
                    else
                    {
                        setDirectionMove( dir );
                        setSleepTime( calcSleepTime( getPassispeed(), MOVE_SPEED ) );
                    }
                }
            }
            else
            {
                deleteDoll();
                return true;
            }
            return false;
        }

        // 時間計測用
        //class DollTimer implements Runnable {
        //    @Override
        public void DollTimerSub( object state )
        {
            if ( _destroyed )
            { // 既に破棄されていないかチェック
                return;
            }
            deleteDoll();
        }
        //}

        public L1DollInstance( L1Npc template, L1PcInstance master, int dollType, int itemObjId )
            : base( template )
        {

            setId( IdFactory.getInstance().nextId() );

            setDollType( dollType );
            setItemObjId( itemObjId );
            //_dollFuture = GeneralThreadPool.getInstance().schedule(new DollTimer(), DOLL_TIME);
            _dollFuture = new Timer( new TimerCallback( DollTimerSub ), null, DOLL_TIME, Timeout.Infinite );

            setMaster( master );
            setX( master.getX() + _random.Next( 5 ) - 2 );
            setY( master.getY() + _random.Next( 5 ) - 2 );
            setMap( master.getMapId() );
            setHeading( 5 );
            setLightSize( template.getLightSize() );

            L1World.getInstance().storeObject( this );
            L1World.getInstance().addVisibleObject( this );
            foreach ( L1PcInstance pc in L1World.getInstance().getRecognizePlayer( this ) )
            {
                onPerceive( pc );
            }
            master.addDoll( this );
            if ( !isAiRunning() )
            {
                startAI();
            }
            if ( isMpRegeneration() )
            {
                master.startMpRegenerationByDoll();
            }
        }

        public void deleteDoll()
        {
            if ( isMpRegeneration() )
            {
                ( (L1PcInstance)_master ).stopMpRegenerationByDoll();
            }
            _master.getDollList().Remove( getId() );
            deleteMe();
        }

        override public void onPerceive( L1PcInstance perceivedFrom )
        {
            perceivedFrom.addKnownObject( this );
            perceivedFrom.sendPackets( new S_DollPack( this, perceivedFrom ) );
        }

        override public void onItemUse()
        {
            if ( !isActived() )
            {
                // １００％の確率でヘイストポーション使用
                useItem( USEITEM_HASTE, 100 );
            }
        }

        override public void onGetItem( L1ItemInstance item )
        {
            if ( getNpcTemplate().get_digestitem() > 0 )
            {
                setDigestItem( item );
            }
            if ( Array.BinarySearch( haestPotions, item.getItem().getItemId() ) >= 0 )
            {
                useItem( USEITEM_HASTE, 100 );
            }
        }

        public int getDollType()
        {
            return _dollType;
        }

        public void setDollType( int i )
        {
            _dollType = i;
        }

        public int getItemObjId()
        {
            return _itemObjId;
        }

        public void setItemObjId( int i )
        {
            _itemObjId = i;
        }

        public int getDamageByDoll()
        {
            int damage = 0;
            int dollType = getDollType();
            if ( dollType == DOLLTYPE_WAREWOLF || dollType == DOLLTYPE_CRUSTANCEAN )
            {
                int chance = _random.Next( 100 ) + 1;
                if ( chance <= 3 )
                {
                    damage = 15;
                    if ( _master is L1PcInstance )
                    {
                        L1PcInstance pc = (L1PcInstance)_master;
                        pc.sendPackets( new S_SkillSound( _master.getId(), 6319 ) );
                    }
                    _master.broadcastPacket( new S_SkillSound( _master.getId(), 6319 ) );
                }
            }
            return damage;
        }

        public bool isMpRegeneration()
        {
            bool isMpRegeneration = false;
            int dollType = getDollType();
            if ( dollType == DOLLTYPE_SUCCUBUS || dollType == DOLLTYPE_ELDER )
            {
                isMpRegeneration = true;
            }
            return isMpRegeneration;
        }

        public int getWeightReductionByDoll()
        {
            int weightReduction = 0;
            int dollType = getDollType();
            if ( dollType == DOLLTYPE_BUGBEAR )
            {
                weightReduction = 20;
            }
            return weightReduction;
        }

        public int getDamageReductionByDoll()
        {
            int damageReduction = 0;
            int dollType = getDollType();
            if ( dollType == DOLLTYPE_GOLEM )
            {
                int chance = _random.Next( 100 ) + 1;
                if ( chance <= 4 )
                {
                    damageReduction = 15;
                }
            }
            return damageReduction;
        }
    }
}
